home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-06  |  23.8 KB  |  1,034 lines

  1. /* 
  2.  * sock.c --
  3.  *
  4.  *    Simple utility functions for managing socket communication
  5.  *
  6.  * Copyright 1992 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/sock.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "jaquith.h"
  21.  
  22. #define BACKLOG 2
  23. #define READ_TIMEOUT 60       /* Socket timeout before message, in secs */
  24. #define WRITE_TIMEOUT 60 
  25.  
  26. typedef struct SockData {
  27.     char *bufPtr;             /* current buffer pointer */
  28.     int bufLen;               /* current buffer length */
  29. } SockData;
  30.  
  31. extern int syserr;
  32.  
  33. /*
  34.  * This lists holds the state of each active socket
  35.  */
  36. static SockData sockList[FD_SETSIZE];
  37.  
  38. /*
  39.  * Utility buffer for formatting messages
  40.  */
  41. static char printBuf[T_MAXSTRINGLEN];
  42.  
  43.  
  44. /*
  45.  *----------------------------------------------------------------------
  46.  *
  47.  * Sock_SendRespHdr --
  48.  *
  49.  *    Send a response to client.
  50.  *
  51.  * Results:
  52.  *    None.
  53.  *
  54.  * Side effects:
  55.  *    None.
  56.  *
  57.  * If we're reporting a failure in status, then err is errno value
  58.  * describing the problem.  If the problem was that the socket went
  59.  * away then this reply will die too.
  60.  *
  61.  *----------------------------------------------------------------------
  62.  */
  63.  
  64. int
  65. Sock_SendRespHdr(sock, status, err)
  66.     int sock;                 /* socket # */
  67.     int status;               /* cmd status */
  68.     int err;                  /* errno if status is no good */
  69. {
  70.     T_RespMsgHdr resp;
  71.  
  72.     resp.version = htonl(MSGVERSION);
  73.     resp.len = htonl(0);
  74.     resp.status = htonl(status);
  75.     resp.errno = htonl(err);
  76.     
  77.     if (Sock_WriteNBytes(sock, (char *)&resp, sizeof(resp)) != sizeof(resp)) {
  78.     return T_IOFAILED;
  79.     } else {
  80.     return T_SUCCESS;
  81.     }
  82. }
  83.  
  84.  
  85. /*
  86.  *----------------------------------------------------------------------
  87.  *
  88.  * Sock_ReadRespHdr --
  89.  *
  90.  *    Retrieve a complete response hdr
  91.  *
  92.  * Results:
  93.  *    none.
  94.  *
  95.  * Side effects:
  96.  *    none.
  97.  *
  98.  *----------------------------------------------------------------------
  99.  */
  100.  
  101. void
  102. Sock_ReadRespHdr(sock, mhdrPtr)
  103.     int sock;                 /* incoming socket */
  104.     T_RespMsgHdr *mhdrPtr;    /* receiving structure */
  105. {
  106.     int readCnt;
  107.     readCnt = Sock_ReadNBytes(sock, (char *)mhdrPtr, sizeof(T_RespMsgHdr));
  108.     if (readCnt != sizeof(T_RespMsgHdr)) {
  109.     sprintf(printBuf, "Server's response is short %d bytes.\n",
  110.         sizeof(T_RespMsgHdr)-readCnt);
  111.     Utils_Bailout(printBuf, BAIL_PRINT);
  112.     }
  113.     mhdrPtr->version = ntohl(mhdrPtr->version);
  114.     mhdrPtr->len = ntohl(mhdrPtr->len);
  115.     mhdrPtr->status = ntohl(mhdrPtr->status);
  116.     mhdrPtr->errno = ntohl(mhdrPtr->errno);
  117.  
  118.     if (mhdrPtr->version != MSGVERSION) {
  119.     Utils_Bailout("Message versions don't agree.\n", BAIL_PRINT);
  120.     }
  121.  
  122. }
  123.  
  124.  
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * Sock_SetSocket--
  129.  *
  130.  *    Save socket state so we can do partial reads.
  131.  *
  132.  * Results:
  133.  *    None.
  134.  *
  135.  * Side effects:
  136.  *    Stow away the number of bytes to be read and the bufPtr.
  137.  *      Then we can update this state as we read junk.
  138.  *
  139.  *----------------------------------------------------------------------
  140.  */
  141.  
  142. void
  143. Sock_SetSocket(sock, bufPtr, bufLen) 
  144.     int sock;                 /* socket # */
  145.     char *bufPtr;             /* buffer to read into */
  146.     int bufLen;               /* size of buffer */
  147. {
  148.     if (sock > FD_SETSIZE) {
  149.     sprintf(printBuf, "SetSocket: Bad socket %d\n", sock);
  150.     Utils_Bailout(printBuf, BAIL_PRINT);
  151.     }
  152.     sockList[sock].bufPtr = bufPtr;
  153.     sockList[sock].bufLen = bufLen;
  154. }
  155.  
  156.  
  157. /*
  158.  *----------------------------------------------------------------------
  159.  *
  160.  * Sock_ReadSocket--
  161.  *
  162.  *    Read as many bytes as possible up to a maximum.
  163.  *
  164.  * Results:
  165.  *    None.
  166.  *
  167.  * Side effects:
  168.  *    Must have called SetSocket to setup the state for this
  169.  *      descriptor otherwise all hell breaks loose.
  170.  *
  171.  *----------------------------------------------------------------------
  172.  */
  173.  
  174. int
  175. Sock_ReadSocket(sock) 
  176.     int sock;                 /* socket # */
  177. {
  178.     int readCnt;
  179.     char *bufPtr;
  180.     int bufLen;
  181.  
  182.     if (sock > FD_SETSIZE) {
  183.     sprintf(printBuf, "ReadSocket: Bad socket %d\n", sock);
  184.     Utils_Bailout(printBuf, BAIL_PRINT);
  185.     }
  186.  
  187.     bufPtr = sockList[sock].bufPtr;
  188.     bufLen = sockList[sock].bufLen;
  189.     if ((bufPtr == (char *)NULL) || (bufLen < 1)) {
  190.     sprintf(printBuf,"ReadSocket: Bad state for socket %d\n", sock);
  191.     Utils_Bailout(printBuf, BAIL_PRINT);
  192.     }
  193.  
  194.     readCnt = read(sock, bufPtr, bufLen);
  195.  
  196.     if (readCnt < 1) {
  197.     return T_IOFAILED;
  198.     } else {
  199.     sockList[sock].bufPtr += readCnt;
  200.     sockList[sock].bufLen -= readCnt;
  201.     }
  202.  
  203.     return (sockList[sock].bufLen);
  204. }
  205.  
  206.  
  207.  
  208. /*
  209.  *----------------------------------------------------------------------
  210.  *
  211.  * Sock_ReadInteger --
  212.  *
  213.  *    Read an integer object
  214.  *
  215.  * Results:
  216.  *    None.
  217.  *
  218.  * Side effects:
  219.  *    None.
  220.  *
  221.  *----------------------------------------------------------------------
  222.  */
  223.  
  224. int
  225. Sock_ReadInteger(sock, intPtr) 
  226.     int sock;                 /* socket # */
  227.     int *intPtr;              /* buffer for integer */
  228. {
  229.     int value;
  230.     int readCnt;
  231.  
  232.     readCnt = Sock_ReadNBytes(sock, (char *)&value, sizeof(int));
  233.     if (readCnt != sizeof(int)) {
  234.     return T_IOFAILED;
  235.     } else {
  236.     *intPtr = ntohl(value);
  237.     return T_SUCCESS;
  238.     }
  239. }
  240.  
  241.  
  242.  
  243. /*
  244.  *----------------------------------------------------------------------
  245.  *
  246.  * Sock_ReadShort --
  247.  *
  248.  *    Read a short object
  249.  *
  250.  * Results:
  251.  *    None.
  252.  *
  253.  * Side effects:
  254.  *    None.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258.  
  259. int
  260. Sock_ReadShort(sock, shortPtr) 
  261.     int sock;                 /* socket # */
  262.     short *shortPtr;          /* buffer for short */
  263. {
  264.     short value;
  265.     int readCnt;
  266.  
  267.     readCnt = Sock_ReadNBytes(sock, (char *)&value, sizeof(short));
  268.     if (readCnt != sizeof(short)) {
  269.     return T_IOFAILED;
  270.     } else {
  271.     *shortPtr = ntohs(value);
  272.     return T_SUCCESS;
  273.     }
  274. }
  275.  
  276.  
  277.  
  278. /*
  279.  *----------------------------------------------------------------------
  280.  *
  281.  * Sock_ReadString --
  282.  *
  283.  *    Read a formatted string 
  284.  *
  285.  * Results:
  286.  *    None.
  287.  *
  288.  * Side effects:
  289.  *    Will allocate a buffer if memFlag == 1
  290.  *
  291.  *----------------------------------------------------------------------
  292.  */
  293.  
  294. int
  295. Sock_ReadString(sock, stringPtrPtr, memFlag) 
  296.     int sock;                 /* socket # */
  297.     char **stringPtrPtr;      /* buffer for string ptr */
  298.     int memFlag;              /* 1 == allocate buffer */
  299. {
  300.     char *charPtr;
  301.     int length;
  302.  
  303.     if ((Sock_ReadInteger(sock, &length) != T_SUCCESS) ||
  304.     (length < 0)) {
  305.     return T_IOFAILED;
  306.     }
  307.  
  308.     if (memFlag) {
  309.     charPtr = MEM_ALLOC("Sock_ReadString", (length+1)*sizeof(char));
  310.     } else {
  311.     charPtr = *stringPtrPtr;
  312.     }
  313.     
  314.     if (length > 0) {
  315.     if (Sock_ReadNBytes(sock, charPtr, length) != length) {
  316.         if (memFlag) {
  317.         MEM_FREE("Sock_ReadString", charPtr);
  318.         }
  319.         return T_IOFAILED;
  320.     }
  321.     }
  322.  
  323.     charPtr[length] = '\0';
  324.     *stringPtrPtr = charPtr;
  325.     return T_SUCCESS;
  326.  
  327. }
  328.  
  329.  
  330. /*
  331.  *----------------------------------------------------------------------
  332.  *
  333.  * Sock_ReadFileStat --
  334.  *
  335.  *    Read T_FileStat
  336.  *
  337.  * Results:
  338.  *    None.
  339.  *
  340.  * Side effects:
  341.  *    May allocate space if memFlag is on.
  342.  *
  343.  *----------------------------------------------------------------------
  344.  */
  345.  
  346. int
  347. Sock_ReadFileStat(sock, statInfoPtr, memFlag)
  348.     int sock;                 /* socket # */
  349.     T_FileStat *statInfoPtr;  /* receiving structure */
  350.     int memFlag;                 /* enable string allocation */
  351. {
  352.     int size;
  353.     static char *buf = NULL;
  354.     static int bufSize = 0;
  355.     int count;
  356.     char *fmt = "CCCCCCIIIIIIIIIIIS";
  357.     char *arr[18];
  358.  
  359.     if ((Sock_ReadInteger(sock, &size) != T_SUCCESS) || (size < 0)) {
  360.     return T_FAILURE;
  361.     }
  362.     if (size > bufSize) {
  363.     if (buf) {
  364.         MEM_FREE("Sock_ReadFileStat", buf);
  365.     }
  366.     buf = (char *)MEM_ALLOC("Sock_ReadFileStat", size*sizeof(char));
  367.     bufSize = size;
  368.     }
  369.  
  370.     if (Sock_ReadNBytes(sock, buf, size) != size) {
  371.     return T_FAILURE;
  372.     }
  373.  
  374.     arr[0] = (char *)&statInfoPtr->fileName;
  375.     arr[1] = (char *)&statInfoPtr->linkName;
  376.     arr[2] = (char *)&statInfoPtr->uname;
  377.     arr[3] = (char *)&statInfoPtr->gname;
  378.     arr[4] = (char *)&statInfoPtr->abstract;
  379.     arr[5] = (char *)&statInfoPtr->fileList;
  380.     arr[6] = (char *)&statInfoPtr->vtime;
  381.     arr[7] = (char *)&statInfoPtr->atime;
  382.     arr[8] = (char *)&statInfoPtr->volId;
  383.     arr[9] = (char *)&statInfoPtr->filemark;
  384.     arr[10] = (char *)&statInfoPtr->tBufId;
  385.     arr[11] = (char *)&statInfoPtr->offset;
  386.     arr[12] = (char *)&statInfoPtr->mode;
  387.     arr[13] = (char *)&statInfoPtr->uid;
  388.     arr[14] = (char *)&statInfoPtr->gid;
  389.     arr[15] = (char *)&statInfoPtr->mtime;
  390.     arr[16] = (char *)&statInfoPtr->size;
  391.     arr[17] = (char *)&statInfoPtr->rdev;
  392.  
  393.     Sock_UnpackData(fmt, buf, &count, arr);
  394. /*
  395.     fprintf(stderr, "file '%s', link '%s'\n",
  396.         statInfoPtr->fileName,statInfoPtr->linkName);
  397.     fprintf(stderr, "u '%s', g '%s'\n",
  398.         statInfoPtr->uname,statInfoPtr->gname);
  399.     fprintf(stderr, "abs '%s', list '%s'\n",
  400.         statInfoPtr->abstract,statInfoPtr->fileList);
  401.  
  402.     fprintf(stderr, "%x %x %x %x %x %x\n",
  403.         statInfoPtr->vtime, statInfoPtr->atime,
  404.         statInfoPtr->volId, statInfoPtr->filemark,
  405.         statInfoPtr->tBufId, statInfoPtr->offset);
  406.     fprintf(stderr, "%x %x %x %x %x %x\n",
  407.         statInfoPtr->mode, statInfoPtr->uid,
  408.         statInfoPtr->gid, statInfoPtr->mtime,
  409.         statInfoPtr->size, (int)statInfoPtr->rdev);
  410. */
  411.     return T_SUCCESS;
  412.     
  413. }
  414.  
  415.  
  416. /*
  417.  *----------------------------------------------------------------------
  418.  *
  419.  * Sock_ReadNBytes --
  420.  *
  421.  *    Read arbitrary object.
  422.  *
  423.  * Results:
  424.  *    None.
  425.  *
  426.  * Side effects:
  427.  *    None.
  428.  *
  429.  *----------------------------------------------------------------------
  430.  */
  431.  
  432. int
  433. Sock_ReadNBytes(sock, buf, bufLen)
  434.     int sock;                 /* incoming socket */
  435.     char *buf;                /* receiving buffer */
  436.     int bufLen;               /* buffer size in bytes */
  437. {
  438.     int readCnt = 0;
  439.     int totalCnt = 0;
  440.     int retryCnt = 0;
  441.  
  442.     if (bufLen < 1) {
  443.     fprintf(stderr,"Sock_ReadNBytes: bad length: %d\n", bufLen);
  444.     fprintf("die %s\n", 0);
  445.     }
  446.  
  447.     while (totalCnt < bufLen) {
  448.     if ((readCnt=read(sock, buf+totalCnt, bufLen-totalCnt)) < 0) {
  449.         syserr = errno;
  450.         fprintf(stderr,"Sock_ReadNBytes: bad read on sock %d. errno %d\n",
  451.             sock, syserr);
  452.         /* A hack for Sprite with timeout problems */
  453.         if ((syserr != ETIMEDOUT) || (retryCnt++ >= 3)) {
  454.         break;
  455.         }
  456.     } else if (readCnt == 0) {
  457.         break;
  458.     } else {
  459.         totalCnt += readCnt;
  460.     }
  461.     }
  462.     return totalCnt;
  463. }
  464.  
  465.  
  466. /*
  467.  *----------------------------------------------------------------------
  468.  *
  469.  * Sock_WriteInteger --
  470.  *
  471.  *    Write an integer object
  472.  *
  473.  * Results:
  474.  *    None.
  475.  *
  476.  * Side effects:
  477.  *    None.
  478.  *
  479.  *----------------------------------------------------------------------
  480.  */
  481.  
  482. int
  483. Sock_WriteInteger(sock, intVal) 
  484.     int sock;                 /* socket # */
  485.     int intVal;               /* integer to write */
  486. {
  487.     int writeCnt;
  488.  
  489.     intVal = htonl(intVal);
  490.     writeCnt = Sock_WriteNBytes(sock, (char *)&intVal, sizeof(intVal));
  491.  
  492.     return (writeCnt == sizeof(intVal)) ? T_SUCCESS : T_IOFAILED;
  493.  
  494. }
  495.  
  496.  
  497.  
  498. /*
  499.  *----------------------------------------------------------------------
  500.  *
  501.  * Sock_WriteShort --
  502.  *
  503.  *    Write a short object
  504.  *
  505.  * Results:
  506.  *    None.
  507.  *
  508.  * Side effects:
  509.  *    None.
  510.  *
  511.  *----------------------------------------------------------------------
  512.  */
  513.  
  514. int
  515. Sock_WriteShort(sock, shortVal) 
  516.     int sock;                 /* socket # */
  517.     short shortVal;           /* short to write */
  518. {
  519.     int writeCnt;
  520.  
  521.     shortVal = htons(shortVal);
  522.     writeCnt = Sock_WriteNBytes(sock, (char *)&shortVal, sizeof(shortVal));
  523.  
  524.     return (writeCnt == sizeof(short)) ? T_SUCCESS : T_IOFAILED;
  525.  
  526. }
  527.  
  528.  
  529. /*
  530.  *----------------------------------------------------------------------
  531.  *
  532.  * Sock_WriteString --
  533.  *
  534.  *    Write a formatted string 
  535.  *
  536.  * Results:
  537.  *    None.
  538.  *
  539.  * Side effects:
  540.  *    Will deallocate buffer if memFlag == 1
  541.  *
  542.  *----------------------------------------------------------------------
  543.  */
  544.  
  545. int
  546. Sock_WriteString(sock, charPtr, memFlag) 
  547.     int sock;                 /* socket # */
  548.     char *charPtr;            /* buffer pointer */
  549.     int memFlag;                 /* 1 == deallocate after writing */
  550. {
  551.     int writeCnt;
  552.     int length;
  553.  
  554.     length = strlen(charPtr);
  555.     if (Sock_WriteInteger(sock, length) != T_SUCCESS) {
  556.     return T_FAILURE;
  557.     }
  558.  
  559.     if (length > 0) {
  560.     writeCnt = Sock_WriteNBytes(sock, charPtr, length);
  561.     if (writeCnt != length) {
  562.         return T_IOFAILED;
  563.     } else if (memFlag) {
  564.         MEM_FREE("WriteString", charPtr);
  565.     }
  566.     }
  567.  
  568.     return T_SUCCESS;
  569.  
  570. }
  571.  
  572.  
  573. /*
  574.  *----------------------------------------------------------------------
  575.  *
  576.  * Sock_WriteFileStat --
  577.  *
  578.  *    Write a T_FileStat.
  579.  *
  580.  * Results:
  581.  *    None.
  582.  *
  583.  * Side effects:
  584.  *    None.
  585.  *
  586.  * Note:
  587.  *      It would be simpler but slower to write out the fields
  588.  *      individually using the appropriate Sock_WriteFoo routine.
  589.  *
  590.  *----------------------------------------------------------------------
  591.  */
  592.  
  593. int
  594. Sock_WriteFileStat(sock, statInfoPtr, memFlag)
  595.     int sock;                 /* socket # */
  596.     T_FileStat *statInfoPtr;  /* file info block to write */
  597.     int memFlag;                 /* 1 == deallocate after writing */
  598. {
  599.     char *buf;
  600.     char *fmt = "CCCCCCIIIIIIIIIIIS";
  601.     char *arr[18];
  602.     int bufLen;
  603.     int retCode = T_SUCCESS;
  604.  
  605.     arr[0] = statInfoPtr->fileName;
  606.     arr[1] = statInfoPtr->linkName;
  607.     arr[2] = statInfoPtr->uname;
  608.     arr[3] = statInfoPtr->gname;
  609.     arr[4] = statInfoPtr->abstract;
  610.     arr[5] = statInfoPtr->fileList;
  611.     arr[6] = (char *)&statInfoPtr->vtime;
  612.     arr[7] = (char *)&statInfoPtr->atime;
  613.     arr[8] = (char *)&statInfoPtr->volId;
  614.     arr[9] = (char *)&statInfoPtr->filemark;
  615.     arr[10] = (char *)&statInfoPtr->tBufId;
  616.     arr[11] = (char *)&statInfoPtr->offset;
  617.     arr[12] = (char *)&statInfoPtr->mode;
  618.     arr[13] = (char *)&statInfoPtr->uid;
  619.     arr[14] = (char *)&statInfoPtr->gid;
  620.     arr[15] = (char *)&statInfoPtr->mtime;
  621.     arr[16] = (char *)&statInfoPtr->size;
  622.     arr[17] = (char *)&statInfoPtr->rdev;
  623.     
  624.     buf = Sock_PackData(fmt, arr, &bufLen);
  625.  
  626.     if ((Sock_WriteInteger(sock, bufLen) != T_SUCCESS) ||
  627.     (Sock_WriteNBytes(sock, buf, bufLen) != bufLen)) {
  628.     retCode = T_IOFAILED;
  629.     } else if (memFlag) {
  630.     Utils_FreeFileStat(statInfoPtr, 0);
  631.     }
  632.  
  633.     MEM_FREE("Sock_WriteFileStat", buf);
  634.     
  635.     return retCode;
  636. }
  637.  
  638.  
  639. /*
  640.  *----------------------------------------------------------------------
  641.  *
  642.  * Sock_WriteNBytes --
  643.  *
  644.  *    Write arbitrary object.
  645.  *
  646.  * Results:
  647.  *    None.
  648.  *
  649.  * Side effects:
  650.  *    None.
  651.  *
  652.  *----------------------------------------------------------------------
  653.  */
  654.  
  655. int
  656. Sock_WriteNBytes(sock, buf, bufLen)
  657.     int sock;                 /* outgoing socket */
  658.     char *buf;                /* source buffer */
  659.     int bufLen;               /* buffer size in bytes */
  660. {
  661.     int writeCnt = 0;
  662.     int totalCnt = 0;
  663.  
  664.     if (bufLen < 1) {
  665.     fprintf(stderr,"Sock_WriteNBytes: bad length: %d\n", bufLen);
  666.     fprintf("die %s\n", 0);
  667.     }
  668.  
  669.     while (totalCnt < bufLen) {
  670.     if ((writeCnt=write(sock, buf+totalCnt, bufLen-totalCnt)) < 1) {
  671.         syserr = errno;
  672.         fprintf(stderr,"Sock_WriteNBytes: writeCnt %d on sock %d. errno %d\n",
  673.             writeCnt, sock, syserr);
  674.         break;
  675.     } else {
  676.         totalCnt += writeCnt;
  677.     }
  678.     }
  679.     return totalCnt;
  680. }
  681.  
  682.  
  683. /*
  684.  *----------------------------------------------------------------------
  685.  *
  686.  * Sock_SetupSocket --
  687.  *
  688.  *    Open socket to the server.
  689.  *
  690.  * Results:
  691.  *    socket number.
  692.  *
  693.  * Side effects:
  694.  *    none.
  695.  *
  696.  *----------------------------------------------------------------------
  697.  */
  698.  
  699. int
  700. Sock_SetupSocket(port, server, dieFlag)
  701.     int port;                 /* port number */
  702.     char *server;             /* server name */
  703.     int dieFlag;              /* Death if we fail */
  704. {
  705.     struct sockaddr_in sockName;
  706.     int nameLen = sizeof(struct sockaddr_in);
  707.     struct hostent *peerInfo;
  708.     int sock;
  709.  
  710.     sockName.sin_family = AF_INET;
  711.     sockName.sin_port = htons(port);
  712.  
  713.     if ((peerInfo=gethostbyname(server)) == NULL) {
  714.     if (dieFlag) {
  715.         sprintf(printBuf, "Can't connect to server %s: gethostbyname",
  716.             server);
  717.         Utils_Bailout(printBuf, BAIL_HERROR);
  718.     } else {
  719.         syserr = errno;
  720.         return T_FAILURE;
  721.     }
  722.     }
  723.  
  724.     bcopy(peerInfo->h_addr_list[0], &sockName.sin_addr,
  725.       peerInfo->h_length);
  726.  
  727.     if ((sock=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  728.     if (dieFlag) {
  729.         sprintf(printBuf, "Can't connect to server %s: socket", server);
  730.         Utils_Bailout(printBuf, BAIL_PERROR);
  731.     } else {
  732.         syserr = errno;
  733.         return T_FAILURE;
  734.     }
  735.     }
  736.  
  737.     if (connect(sock, (struct sockaddr *)&sockName, nameLen) == -1) {
  738.     if (dieFlag) {
  739.         sprintf(printBuf, "Can't connect to server %s, port %d: connect",
  740.             server, port);
  741.         Utils_Bailout(printBuf, BAIL_PERROR);
  742.     } else {
  743.         syserr = errno;
  744.         return T_FAILURE;
  745.     }
  746.     }
  747.  
  748.     return(sock);
  749. }
  750.  
  751.  
  752. /*
  753.  *----------------------------------------------------------------------
  754.  *
  755.  * Sock_SetupEarSocket --
  756.  *
  757.  *    Prepare the initial socket connection to receive incoming
  758.  * connection requests.
  759.  *
  760.  * Results:
  761.  *    none.
  762.  *
  763.  * Side effects:
  764.  *    Creates a TCP socket.
  765.  *
  766.  *----------------------------------------------------------------------
  767.  */
  768.  
  769. int
  770. Sock_SetupEarSocket(portPtr)
  771.     int *portPtr;             /* port number */
  772. {
  773.     int earSocket;
  774.     struct sockaddr_in earName;
  775.     int nameLen = sizeof(struct sockaddr_in);
  776.  
  777.     if ((earSocket=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  778.     Utils_Bailout("Can't set up listening socket: socket", BAIL_PERROR);
  779.     }
  780.  
  781.     bzero((char*)&earName, nameLen);
  782.     earName.sin_family = AF_INET;
  783.     earName.sin_addr.s_addr = INADDR_ANY;
  784.     earName.sin_port = htons((u_short)(*portPtr));
  785.  
  786.     if (bind(earSocket, (struct sockaddr *)&earName, nameLen)) {
  787.     sprintf(printBuf, "Can't set up listening socket on port %d: bind", (int)*portPtr);
  788.     Utils_Bailout(printBuf, BAIL_PERROR);
  789.     }
  790.     
  791.     if (getsockname(earSocket, (struct sockaddr *)&earName, &nameLen)) {
  792.     Utils_Bailout("Can't set up listing socket: getsockname", BAIL_PERROR);
  793.     }
  794.  
  795.     *portPtr = (int) ntohs(earName.sin_port);
  796.     if (listen(earSocket, BACKLOG) == -1) {
  797.     Utils_Bailout("Can't set up listing socket: listen", BAIL_PERROR);
  798.     }
  799.  
  800.     /* set the socket to close on exec */
  801.     if (fcntl(earSocket, F_SETFD, 1) == -1) {
  802.     Utils_Bailout("Can't set up listing socket: fcntl", BAIL_PERROR);
  803.     }
  804.  
  805.     return(earSocket);
  806.  
  807. }
  808.  
  809.  
  810. /*
  811.  *----------------------------------------------------------------------
  812.  *
  813.  * Sock_PackData --
  814.  *
  815.  *    Convert array of objects strings to network form.
  816.  *
  817.  * Results:
  818.  *    Buffer holding network-ready bytes, and its length.
  819.  *
  820.  * Side effects:
  821.  *    none.
  822.  *
  823.  *----------------------------------------------------------------------
  824.  */
  825.  
  826. char *
  827. Sock_PackData(fmt, objArray, packedLenPtr)
  828.     char *fmt;                /* format string. I=int, S=short, C=char */
  829.     char **objArray;          /* array of ptrs to objects */
  830.     int *packedLenPtr;        /* length of resulting packed buffer */
  831. {
  832.     int i;
  833.     int intVal = 0;
  834.     int hIntVal;
  835.     short shortVal;
  836.     char *buf;
  837.     char *workingPtr;
  838.  
  839.     for (i=0; fmt[i]; i++) {
  840.     switch (fmt[i]) {
  841.     case 'I':
  842.     case 'i':
  843.         intVal += sizeof(int);
  844.         break;
  845.     case 'S':
  846.     case 's':
  847.         intVal += sizeof(short);
  848.         break;
  849.     case 'C':
  850.     case 'c':
  851.         intVal += strlen(objArray[i])+sizeof(int);
  852.         break;
  853.     default:
  854.         sprintf(printBuf, "Sock_PackData: bad object type: %c\n", fmt[i]);
  855.         Utils_Bailout(printBuf, BAIL_PRINT);
  856.         break;
  857.     }
  858.  
  859.     }
  860.  
  861.     *packedLenPtr = intVal;
  862.     buf = workingPtr = (char *)MEM_ALLOC("Sock_PackData", intVal*sizeof(char));
  863.  
  864.     for (i=0; fmt[i]; i++) {
  865.     switch (fmt[i]) {
  866.     case 'I':
  867.     case 'i':
  868.         intVal = htonl(*(int *)objArray[i]);
  869.         bcopy((char *)&intVal, workingPtr, sizeof(int));
  870.         workingPtr += sizeof(int);
  871.         break;
  872.     case 'S':
  873.     case 's':
  874.         shortVal = htons(*(short *)objArray[i]);
  875.         bcopy((char *)&shortVal, workingPtr, sizeof(short));
  876.         workingPtr += sizeof(short);
  877.         break;
  878.     case 'C':
  879.     case 'c':
  880.         intVal = strlen(objArray[i]);
  881.         hIntVal = htonl(intVal);
  882.         bcopy((char *)&hIntVal, workingPtr, sizeof(int));
  883.         workingPtr += sizeof(int);
  884.         bcopy(objArray[i], workingPtr, intVal);
  885.         workingPtr += intVal;
  886.         break;
  887.     default:
  888.         sprintf(printBuf, "Sock_PackData: bad object type: %c\n", fmt[i]);
  889.         Utils_Bailout(printBuf, BAIL_PRINT);
  890.         break;
  891.     }
  892.  
  893.     }
  894.  
  895.     return(buf);
  896. }
  897.  
  898.  
  899. /*
  900.  *----------------------------------------------------------------------
  901.  *
  902.  * Sock_UnpackData --
  903.  *
  904.  *    Convert network bytes to array of objects.
  905.  *
  906.  * Results:
  907.  *    Array of objects is filled in.
  908.  *
  909.  * Side effects:
  910.  *    none.
  911.  *
  912.  *----------------------------------------------------------------------
  913.  */
  914.  
  915. int
  916. Sock_UnpackData(fmt, buf, countPtr, objArray)
  917.     char *fmt;                /* format string. I=int, S=short, C=char */
  918.     char *buf;                /* buf to be parsed */
  919.     int *countPtr;            /* number of bytes processed */
  920.     char **objArray[];        /* list of object ptr locations */
  921. {
  922.     int i;
  923.     int intVal;
  924.     int shortVal;
  925.     char *workingPtr = buf;
  926.     char *stringPtr;
  927.     
  928.     for (i=0; fmt[i]; i++) {
  929.     switch (fmt[i]) {
  930.     case 'I':
  931.     case 'i':
  932.         bcopy(workingPtr, (char *)&intVal, sizeof(int));
  933.         intVal = (int)ntohl(intVal);
  934.         bcopy(&intVal, (char *)objArray[i], sizeof(int));
  935.         workingPtr += sizeof(int);
  936.         break;
  937.     case 'S':
  938.     case 's':
  939.         bcopy(workingPtr, (char *)&shortVal, sizeof(short));
  940.         shortVal = (short)ntohs(shortVal);
  941.         bcopy(&shortVal, (char *)objArray[i], sizeof(short));
  942.         workingPtr += sizeof(short);
  943.         break;
  944.     case 'C':
  945.     case 'c':
  946.         bcopy(workingPtr, (char *)&intVal, sizeof(int));
  947.         workingPtr += sizeof(int);
  948.         intVal = (int)ntohl(intVal);
  949.         stringPtr =
  950.         (char *) MEM_ALLOC("Sock_UnpackData",(intVal+1)*sizeof(char));
  951.         bcopy((char *)&stringPtr, (char *)objArray[i], sizeof(char *));
  952.         bcopy(workingPtr, stringPtr, intVal);
  953.         *(stringPtr+intVal) = '\0';
  954.         workingPtr += intVal;
  955.         break;
  956.     default:
  957.         sprintf(printBuf, "Sock_UnpackData: bad object type: %c\n",fmt[i]);
  958.         Utils_Bailout(printBuf, BAIL_PRINT);
  959.         break;
  960.     }
  961.  
  962.     }
  963.  
  964.     *countPtr = (workingPtr-buf);
  965.     return T_SUCCESS;
  966. }
  967.  
  968.  
  969. /*
  970.  *----------------------------------------------------------------------
  971.  *
  972.  * Sock_SendReqHdr --
  973.  *
  974.  *    Send a formatted request header
  975.  *
  976.  * Results:
  977.  *    none.
  978.  *
  979.  * Side effects:
  980.  *    none.
  981.  *
  982.  *----------------------------------------------------------------------
  983.  */
  984.  
  985. void
  986. Sock_SendReqHdr(sock, cmd, ticket, mail, arch, flags)
  987.     int sock;                 /* outgoing socket */
  988.     int cmd;                  /* command */
  989.     AuthHandle ticket;        /* authorization ticket */
  990.     char *mail;               /* mail address */
  991.     char *arch;               /* archive name */
  992.     int flags;                /* force and sync flags */
  993. {
  994.     int localFlags = flags;
  995.     static char fmt[] = "CCCC";
  996.     char *objList[6];
  997.     int packedObjLen;
  998.     char *packedObjBuf;
  999.     int packedHdrLen;
  1000.     char *packedHdrBuf;
  1001.     uid_t shortUid;
  1002.     gid_t shortGid;
  1003.     int version = MSGVERSION;
  1004.     static char hdrFmt[] = "IIIII";
  1005.  
  1006.     shortUid = getuid();
  1007.     shortGid = getgid();
  1008.     objList[0] = Utils_GetLoginByUid((int)shortUid);
  1009.     objList[1] = Utils_GetGroupByGid((int)shortGid);
  1010.     objList[2] = mail;
  1011.     objList[3] = arch;
  1012.     
  1013.     if (cmd == T_CMDLS) {
  1014.     localFlags |= T_NODATA;
  1015.     }
  1016.  
  1017.     packedObjBuf = Sock_PackData(fmt, objList, &packedObjLen);
  1018.  
  1019.     objList[0] = (char *)&version;
  1020.     objList[1] = (char *)&cmd;
  1021.     objList[2] = (char *)&packedObjLen;
  1022.     objList[3] = (char *)&localFlags;
  1023.     objList[4] = (char *)&ticket;
  1024.  
  1025.     packedHdrBuf = Sock_PackData(hdrFmt, objList, &packedHdrLen);
  1026.  
  1027.     Sock_WriteNBytes(sock, packedHdrBuf, packedHdrLen);
  1028.     Sock_WriteNBytes(sock, packedObjBuf, packedObjLen);
  1029.  
  1030.     MEM_FREE("Sock_SendReqHdr", packedHdrBuf);
  1031.     MEM_FREE("Sock_SendReqHdr", packedObjBuf);
  1032.  
  1033. }
  1034.